﻿using Aspects.Cache;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace CommConfig
{
    /// <summary>
    /// """请基于```内的内容回答问题。"
    ////\```
    ////	{context
    ////}
    ////\```
    ////	我的问题是：{question}。
    ////"""
    /// </summary>
    public static class XmlDeal
    {
        private static List<NodeInfo> GetXPathNodes(XElement parentNode, string strPath, List<XmlConfig> config)
        {
            List<NodeInfo> listXpath = new List<NodeInfo>();
            parentNode.Attributes().ToList().ForEach(attr =>
            {
                string strName = attr.Name.LocalName;
                string strXpath = string.Format("{0}/@{1}", strPath, strName);
                if (!config.Exists(a => a.Xpathval == strXpath && a.Type == "排除"))
                {
                    NodeInfo node = new NodeInfo()
                    {
                        nodePath = strXpath,
                        nodeName = strName,
                        nodeValue = attr.Value.Replace(" ", "").Replace(";", "").Replace(",", ""),
                        orderLevel = int.Parse(config.Find(a => a.Xpathval == strXpath)?.OrderLevel ?? "0")
                    };
                    var nn1 = config.Find(n => n.Xpathval == strXpath && n.Convertval != "");
                    if (nn1 != null)
                    {
                        node.nodeName = nn1.Convertval;
                    }
                    listXpath.Add(node);
                }
            });

            if (parentNode.HasElements)
            {
                foreach (var node in parentNode.Elements())
                {
                    var t1 = string.Format("{0}/{1}", strPath, node.Name.LocalName);
                    var gg1 = config.Find(p => t1 == p.Xpathval && p.Type == "使用节点值");
                    if (gg1 != null)
                    {
                        var nnn1 = new NodeInfo
                        {
                            nodePath = t1,
                            nodeName = gg1.Convertval,
                            orderLevel = int.Parse(config.Find(a => a.Xpathval == t1)?.OrderLevel ?? "0")
                        };
                        //数组格式
                        List<string> attrs = GetGroupNodeVal(node, t1, config);
                        nnn1.nodeValue = string.Join(";", attrs.OrderBy(p => p).ToList());
                        listXpath.Add(nnn1);
                    }
                    else
                    {
                        listXpath.AddRange(GetXPathNodes(node, t1, config));
                    }
                }
            }
            return listXpath;
        }
        private static List<string> GetGroupNodeVal(XElement node, string nodePath, List<XmlConfig> config)
        {
            //数组格式
            List<string> attrs = new List<string>();
            foreach (var item in node.Attributes())
            {
                var strXpath = $"{nodePath}/@{item.Name.LocalName}";
                if (!config.Exists(a => a.Xpathval == strXpath && a.Type == "排除"))
                {
                    var ii1 = item.Name;
                    var cc1 = config.Find(b => b.Xpathval == strXpath);
                    if (cc1 != null)
                    {
                        ii1 = cc1.Convertval;
                    }
                    attrs.Add($"{ii1} {item.Value.Replace(" ", "").Replace(";", "").Replace(",", "")}");
                }
            }
            if (node.HasElements)
            {
                foreach (var subnode in node.Elements())
                {
                    attrs.AddRange(GetGroupNodeVal(subnode, $"{nodePath}/{subnode.Name}", config));
                }
            }
            return attrs;
        }
        /// <summary>
        /// Gets the content of the XML.根据xml要素信息生成要素,生成多个不同排序的
        /// </summary>
        /// <param name="xml">The XML.</param>
        /// <param name="modelCode">The model code.</param>
        /// <returns></returns>
        public static List<string> GetXmlContent(string xml, string modelCode)
        {
            try
            {
                List<NodeInfo> listXpath = new List<NodeInfo>();
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(xml);

                foreach (XmlNode node in xmlDoc.ChildNodes)
                {
                    listXpath.AddRange(GetXPath(node, $"/{node.Name}", GetXmlConfig(modelCode)));
                }
                List<string> result = listXpath.Select(item =>
                {
                    return $"{item.nodeName}:{item.nodeValue}";
                }).Where(p => p != ":" && !string.IsNullOrWhiteSpace(p)).ToList();
                List<string> rr1 = new List<string>
                {
                    string.Join("#", result)
                };
                ////rr1.Add(string.Join(",", result.OrderBy(p => p)));
                ////Random random = new Random();
                ////rr1.Add(string.Join(",", result.OrderBy(p => random.Next())));
                return rr1;
            }
            catch
            {
                return new List<string>() { xml };
            }
        }
        /// <summary>
        /// 获取xml配置
        /// </summary>
        /// <returns>excludes\needs\groups</returns>
#if !DEBUG
        [MemoryCache]
#endif
        private static List<XmlConfig> GetXmlConfig(string modeCode)
        {
            XDocument doc = XDocument.Load(Path.Combine(AppContext.BaseDirectory, $"{modeCode}.xml"));
            var configs = doc.Root.Elements("config");
            return configs.Select(p => new XmlConfig
            {
                Xpathval = p.Attributes().FirstOrDefault(a => a.Name == "xpathval")?.Value,
                Convertval = p.Attributes().FirstOrDefault(a => a.Name == "convertval")?.Value,
                Type = p.Attributes().FirstOrDefault(a => a.Name == "type")?.Value,
                 OrderLevel= p.Attributes().FirstOrDefault(a => a.Name == "orderlevel")?.Value,
            }).ToList();

        }
        /// <summary>
        /// 获取Xpath集合
        /// 20240408syjie
        /// </summary>
        /// <param name="parentNode"></param>
        /// <param name="strPath"></param>
        /// <returns></returns>
        private static List<NodeInfo> GetXPath(XmlNode parentNode, string strPath, List<XmlConfig> config)
        {
            List<NodeInfo> listXpath = new List<NodeInfo>();

            if (parentNode.Attributes != null)
            {
                foreach (XmlAttribute item in parentNode.Attributes)
                {
                    string strName = item.Name;
                    string strXpath = string.Format("{0}/@{1}", strPath, strName);
                    if (!config.Exists(a => a.Xpathval == strXpath && a.Type == "排除"))
                    {
                        NodeInfo node = new NodeInfo()
                        {
                            nodePath = strXpath,
                            nodeName = strName,
                            nodeValue = item.Value.Replace(" ", "").Replace(";", "").Replace(",", "")
                        };
                        var nn1 = config.Find(n => n.Xpathval == strXpath && n.Convertval != "");
                        if (nn1 != null)
                        {
                            node.nodeName = nn1.Convertval;
                        }
                        listXpath.Add(node);
                    }
                }
            }

            if (parentNode.ChildNodes != null)
            {
                foreach (XmlNode node in parentNode.ChildNodes)
                {
                    var t1 = string.Format("{0}/{1}", strPath, node.Name);
                    var gg1 = config.Find(p => t1 == p.Xpathval && p.Type == "使用节点值");
                    if (gg1 != null)
                    {
                        var nnn1 = new NodeInfo
                        {
                            nodePath = t1,
                            nodeName = gg1.Convertval,
                        };
                        //数组格式
                        List<string> attrs = GetGroupNodeVal(node, t1, config);
                        nnn1.nodeValue = string.Join(";", attrs.ToList());
                        nnn1.nodeValue = nnn1.nodeValue.Replace(";remove ", " ");
                        nnn1.nodeValue = nnn1.nodeValue.Replace(";remove", " ");
                        nnn1.nodeValue = nnn1.nodeValue.Replace("remove ", " ");
                        listXpath.Add(nnn1);
                    }
                    else
                    {
                        listXpath.AddRange(GetXPath(node, t1, config));
                    }
                }
            }
            return listXpath;
        }
        private static List<string> GetGroupNodeVal(XmlNode node, string nodePath, List<XmlConfig> config)
        {
            //数组格式
            List<string> attrs = new List<string>();
            List<int> ints = new List<int>();
            foreach (XmlAttribute item in node.Attributes)
            {
                var strXpath = $"{nodePath}/@{item.Name}";
                if (!config.Exists(a => a.Xpathval == strXpath && a.Type == "排除"))
                {
                    var ii1 = item.Name;
                    var cc1 = config.Find(b => b.Xpathval == strXpath);
                    if (cc1 != null)
                    {
                        ii1 = cc1.Convertval;
                    }
                    var val11 = $"{ii1} {item.Value.Replace(" ", "").Replace(";", "").Replace(",", "")}";
                    
                    var oor = int.Parse(config.Find(a => a.Xpathval == strXpath)?.OrderLevel ?? "0");
                    var ttt1=ints.FindIndex(a=>a!=0 && a>oor);
                    if (ttt1 != -1)
                    {
                        attrs.Insert(ttt1, val11);
                        ints.Insert(ttt1, oor);
                    }
                    else
                    {
                        attrs.Add(val11);
                        ints.Add(oor);
                    }
                }
            }
            if (node.ChildNodes != null)
            {
                foreach (XmlNode subnode in node.ChildNodes)
                {
                    attrs.AddRange(GetGroupNodeVal(subnode, $"{nodePath}/{subnode.Name}", config));
                }
            }
            return attrs;
        }
    }
    class NodeInfo
    {
        public string nodePath { get; set; }
        public string nodeName { get; set; }
        public string nodeValue { get; set; }

        public int orderLevel { get; set; } = 0;
    }
}
